package com.mimo.logic.blocking.service.impl;

import java.text.MessageFormat;
import java.time.Duration;
import java.util.Arrays;
import java.util.Objects;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import com.mimo.common.logic.code.StatusCode;
import com.mimo.logic.blocking.constants.DenyKey;
import com.mimo.logic.blocking.constants.DenyOperation;
import com.mimo.logic.blocking.dto.AddDenyItemReq;
import com.mimo.logic.blocking.dto.RemoveDenyItemReq;
import com.mimo.logic.blocking.service.IAccessiableService;
import com.mimo.logic.room.service.IRoomService;

@Service
public class UserAccessiableImpl implements IAccessiableService {
  private static final Logger log = LoggerFactory.getLogger(UserAccessiableImpl.class);
  @Autowired
  private RedisTemplate<String, String> redisTemplate;

  @Resource
  private IRoomService roomService;

  /**
   * user 是否在 target 的封禁列表中
   */
  @Override
  public StatusCode checkAccessiable(String user, String target, DenyOperation deny) {
    StatusCode code = StatusCode.Success;
    String key = null;
    long now = System.currentTimeMillis();
    if (deny == DenyOperation.GlobalBlock) {
      key = DenyKey.LOGIC_DENY_GLOBAL;
    } else if (deny == DenyOperation.GlobalMute) {
      key = DenyKey.LOGIC_DENY_GLOBAL_MUTE;
    } else if (deny == DenyOperation.P2P) {
      Objects.requireNonNull(target, "target");
      key = MessageFormat.format(DenyKey.LOGIC_DENY_P2P, target);
    } else if (deny == DenyOperation.JoinRoom) {
      Objects.requireNonNull(target, "target");
      key = MessageFormat.format(DenyKey.LOGIC_DENY_ROOM_JOINT, target);
    } else if (deny == DenyOperation.RoomMute) {
      Objects.requireNonNull(target, "target");
      key = MessageFormat.format(DenyKey.LOGIC_DENY_ROOM_MUTE, target);
    } else {
      throw new IllegalArgumentException();
    }

    Double expired = redisTemplate.opsForZSet().score(key, user);
    if (Objects.nonNull(expired)) {
      if (now >= expired.longValue()) {
        redisTemplate.opsForZSet().remove(key, user);
      } else {
        code = deny.getStatusCode();
        log.warn("权限检查异常: user:{} , target:{}, denyType:{},now:{},expired:{}", user, target, deny, now,
            expired.longValue());
      }
    }

    return code;
  }

  @Override
  public void addDenyItem(AddDenyItemReq req) {
    String key = null;
    if (req.getType() == DenyOperation.GlobalBlock) {
      key = DenyKey.LOGIC_DENY_GLOBAL;
    } else if (req.getType() == DenyOperation.GlobalMute) {
      key = DenyKey.LOGIC_DENY_GLOBAL_MUTE;
    } else if (req.getType() == DenyOperation.P2P) {
      Objects.requireNonNull(req.getTarget(), "target");
      key = MessageFormat.format(DenyKey.LOGIC_DENY_P2P, req.getTarget());
    } else if (req.getType() == DenyOperation.JoinRoom) {
      Objects.requireNonNull(req.getTarget(), "target");
      key = MessageFormat.format(DenyKey.LOGIC_DENY_ROOM_JOINT, req.getTarget());

      // 如果是被禁止加入聊天室，则需要在添加的同时,把用户强制移出聊天室
      String roomId = req.getTarget();
      String userId = req.getSource();
      roomService.leave(roomId, userId);

    } else if (req.getType() == DenyOperation.RoomMute) {
      Objects.requireNonNull(req.getTarget(), "target");
      key = MessageFormat.format(DenyKey.LOGIC_DENY_ROOM_MUTE, req.getTarget());
    } else {
      throw new IllegalArgumentException();
    }

    long expired = System.currentTimeMillis() + Duration.ofMinutes(req.getPeriod()).toMillis();
    redisTemplate.opsForZSet().add(key, req.getSource(), expired);
  }

  @Override
  public void removeDenyItem(RemoveDenyItemReq req) {
    String key = null;
    if (req.getType() == DenyOperation.GlobalBlock) {
      key = DenyKey.LOGIC_DENY_GLOBAL;
    } else if (req.getType() == DenyOperation.GlobalMute) {
      key = DenyKey.LOGIC_DENY_GLOBAL_MUTE;
    } else if (req.getType() == DenyOperation.P2P) {
      Objects.requireNonNull(req.getTarget(), "target");
      key = MessageFormat.format(DenyKey.LOGIC_DENY_P2P, req.getTarget());
    } else if (req.getType() == DenyOperation.JoinRoom) {
      Objects.requireNonNull(req.getTarget(), "target");
      key = MessageFormat.format(DenyKey.LOGIC_DENY_ROOM_JOINT, req.getTarget());
    } else if (req.getType() == DenyOperation.RoomMute) {
      Objects.requireNonNull(req.getTarget(), "target");
      key = MessageFormat.format(DenyKey.LOGIC_DENY_ROOM_MUTE, req.getTarget());
    } else {
      throw new IllegalArgumentException();
    }
    redisTemplate.opsForZSet().remove(key, req.getSource());
  }

  @Override
  public void onRoomDestory(String roomId) {
    redisTemplate.delete(Arrays.asList(MessageFormat.format(DenyKey.LOGIC_DENY_ROOM_JOINT, roomId),
        MessageFormat.format(DenyKey.LOGIC_DENY_ROOM_MUTE, roomId)));
  }

}
